home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / effects / dimmer2effect / effect.c < prev    next >
Encoding:
Text File  |  2000-06-23  |  27.2 KB  |  980 lines

  1. /*
  2.     Dimmer2Effect.c - a sample QuickTime video effect.
  3.     
  4.     This effect uses a single source as input, and renders that source with
  5.     a dim value that starts at full on, and ramps to full off.  This isn't very
  6.     useful as a real effect, but shows instead how to create an effect.
  7.     
  8.     READ THIS PARAGRAPH BEFORE DOING ANYTHING ELSE IN THIS FILE:
  9.     To find things to change to implement your effect, seach for *** CHANGE ***.  
  10.     Code that will require modification is bracketted by CHANGE/END CHANGE.
  11.     
  12.     There are eleven places to change code, and one place where you write new
  13.     code that implements your actual effect.  MAKE SURE YOU LOOK AT ALL OF THEM.
  14.     
  15.     *IMPORTANT*
  16.     
  17.     You MUST also ensure that the Effect.r file is kept in sync with this code.
  18.     In particular it is very important that you update the 'atms' resource
  19.     description so that the parameters of your effect are correctly described.
  20.     Full details of the format of the 'atms' resource can be found in the Effects
  21.     chapter of the QT 3.0 documentation
  22.     
  23.     ALSO PLEASE NOTE THAT THE LINK WARNING ABOUT THE COMPONENT DISPATCH ENTRY POINT
  24.     NOT BEING A ROUTINE DESCRIPTOR IS NORMAL AND CAN BE IGNORED!
  25.     
  26.     written by Tom Dowdy and Dan Crow
  27.     copyright © 1997-1998 Apple Computer, Inc.
  28.     All rights reserved.
  29. */
  30.  
  31.  
  32. // --------------------------------------------------------------------------------------
  33. // INCLUDES
  34. // --------------------------------------------------------------------------------------
  35.  
  36. #include <MacMemory.h>
  37. #include <Resources.h>
  38. #include <Quickdraw.h>    
  39. #include <QDOffscreen.h>
  40. #include <OSUtils.h>
  41. #include <Errors.h>
  42. #include <FixMath.h>
  43. #include <Movies.h>
  44. #include <Endian.h>
  45. #include <ImageCodec.h>
  46.  
  47. #include "EffectDefinitions.h"
  48.  
  49. #if PRAGMA_STRUCT_ALIGN
  50.     #pragma options align=mac68k
  51. #endif
  52.  
  53. #include "EffectUtilities.h"
  54.  
  55.  
  56. // --------------------------------------------------------------------------------------
  57. // INTERNAL DEFINES
  58. // --------------------------------------------------------------------------------------
  59.  
  60. // *** CHANGE *** This defines the number of frames that can be queued for
  61. // asynchronous rendering by this effect.  The value 0 indicates the effect
  62. // runs synchronously.
  63. #define kMaxAsyncFrames        0
  64. // *** END CHANGE ***
  65.  
  66. // *** CHANGE *** Change if your effect accepts multiple sources.  This value
  67. // is the maximum number of sources this effect operates on.
  68. #define    kMaxSources            2
  69. // *** END CHANGE ***
  70.  
  71. // --------------------------------------------------------------------------------------
  72. // INTERNAL TYPEDEFS
  73. // --------------------------------------------------------------------------------------
  74.  
  75. // Structure used to store inforation about each source
  76. typedef struct SourceRecord {                        
  77.     CDSequenceDataSourcePtr    src;
  78.     void                    *srcBaseAddr;
  79.     long                    srcRowBytes;
  80. } SourceRecord;
  81.  
  82. // This is the structure used to store information for drawing a single frame of the effect
  83. typedef struct BlitGlobals {                            
  84.     SourceRecord        sources[kMaxSources];    // inputs
  85.  
  86.     void                *dstBaseAddr;            // output base address
  87.     long                dstRowBytes;            // output row bytes
  88.     long                height;                    // output height
  89.     long                width;                    // output width
  90.     short                destDepth;                // output depth
  91.     OSType                dstPixelFormat;            // output pixel format
  92.     
  93.     // *** CHANGE *** Here is where we store values relating to a single frame
  94.     // of the effect.  These are the parameters to the effect, modified by the
  95.     // percentage into the effect which we are.
  96.     
  97.     long                direction;
  98.     short                dimValue;                // dimming value, from 0 to 255
  99.     
  100.     // *** END CHANGE ***
  101. } BlitGlobals;
  102.  
  103.  
  104. // global data per instance. This holds data for the entire effect as it runs its course.
  105. typedef struct EffectGlobals
  106.     {
  107.     ComponentInstance    self;        // ourselves
  108.     ComponentInstance    target;        // top of the calling chain
  109.     ComponentInstance    delegate;    // if we can't handle an effect, this one can
  110.     
  111.     BlitGlobals            blitter;    // information for drawing the data
  112.     OSType                **wantedDestinationPixelTypeH;
  113.     
  114.     #if kMaxAsyncFrames > 0
  115.         volatile short    asyncCount;    // number of outstanding frames we have        
  116.     #endif
  117.     
  118.     // parameter/source/dest seed tracking
  119.     long                        initialized;
  120.     long                        frameNumber;            
  121.     long                        virtualDuration;
  122.     long                        majorSourceChangeSeed;
  123.     
  124.     TweenGlobals                tweenGlobals;
  125.  
  126.     // *** CHANGE *** PLACE PARAMETERS FOR YOUR EFFECT HERE
  127.     
  128.     long                        direction;    // direction of blit.  0 for dim to bright, 255 for bright to dim
  129.         
  130.     TweenContainerRecord        percentage;
  131.     
  132.     // *** END CHANGE ***
  133. } EffectGlobals;
  134.  
  135. // --------------------------------------------------------------------------------------
  136. // DISPATCHER
  137. // --------------------------------------------------------------------------------------
  138. /************************************************************************************ 
  139.  *    This is the main dispatcher for our codec. All calls from the codec manager
  140.  *    will come through here, with a unique selector and corresponding parameter block.
  141.  *
  142.  *    This routine must be first in the code segment of the codec component.
  143.  *
  144.  *    We use the normal dispatcher rather than the codec dispatcher as we need to
  145.  *    implement the extra effects routines on top of the codec ones.
  146.  */
  147. /************************************************************************************/
  148. // Begin Dispatch Stuff
  149.  
  150. // Used by Component Dispatch Helper to call our routines
  151. #define CALLCOMPONENT_BASENAME()        EffectsFrame
  152. #define    CALLCOMPONENT_GLOBALS()            EffectGlobals * storage
  153.  
  154. // Used by Type's .k.h to create prototypes for our routines
  155. #define    IMAGECODEC_BASENAME()            CALLCOMPONENT_BASENAME()
  156. #define    IMAGECODEC_GLOBALS()            CALLCOMPONENT_GLOBALS()
  157.  
  158. // Used by SubType's .k.h to create prototypes for our routines
  159. #define    IMAGECODECEFFECT_BASENAME()        CALLCOMPONENT_BASENAME()
  160. #define    IMAGECODECEFFECT_GLOBALS()        CALLCOMPONENT_GLOBALS()
  161.  
  162. // Other defines for Component Dispatch Helper
  163. #define COMPONENT_DISPATCH_FILE            "EffectDispatch.h"    // describes what to dispatch
  164. #define    GET_DELEGATE_COMPONENT()        (storage->delegate)    // how to find delegate component
  165.  
  166. #define COMPONENT_UPP_SELECT_ROOT()        ImageCodec            // root for Type's UPP_PREFIX and SELECT_PREFIX        
  167.  
  168. #include "Components.k.h"                // StdComponent's .k.h
  169. #include "ImageCodec.k.h"                // Type's .k.h
  170. #include "ComponentDispatchHelper.c"    // make our dispatcher and cando
  171.  
  172. // End Dispatch Stuff
  173. /************************************************************************************/
  174.  
  175. // --------------------------------------------------------------------------------------
  176. // MULTIPLE BIT-DEPTH AND PIXEL FORMATS
  177. //    For clarity/reuse sake, the drawing code is being kept separate from the component
  178. //    interface code.
  179. // --------------------------------------------------------------------------------------
  180.  
  181.  
  182. // 16BE555
  183. #define EffectFilter16 EffectFilter16BE555
  184. #define srcIs16BE555 1
  185. #define dstIs16BE555 1
  186. #include "EffectFilter16.c"
  187. #undef EffectFilter16
  188. #undef srcIs16BE555
  189. #undef dstIs16BE555
  190.  
  191. #if NON_MAC_PIXEL_FORMATS
  192. // 16LE555
  193. #define EffectFilter16 EffectFilter16LE555
  194. #define srcIs16LE555 1
  195. #define dstIs16LE555 1
  196. #include "EffectFilter16.c"
  197. #undef EffectFilter16
  198. #undef srcIs16LE555
  199. #undef dstIs16LE555
  200.  
  201. // 16LE565
  202. #define EffectFilter16 EffectFilter16LE565
  203. #define srcIs16LE565 1
  204. #define dstIs16LE565 1
  205. #include "EffectFilter16.c"
  206. #undef EffectFilter16
  207. #undef srcIs16LE565
  208. #undef dstIs16LE565
  209.  
  210. #endif
  211.  
  212. // 32ARGB
  213. #define EffectFilter32 EffectFilter32ARGB
  214. #define srcIs32ARGB 1
  215. #define dstIs32ARGB 1
  216. #include "EffectFilter32.c"
  217. #undef EffectFilter32
  218. #undef srcIs32ARGB
  219. #undef dstIs32ARGB
  220. #if NON_MAC_PIXEL_FORMATS
  221. // 32BGRA
  222. #define EffectFilter32 EffectFilter32BGRA
  223. #define srcIs32BGRA 1
  224. #define dstIs32BGRA 1
  225. #include "EffectFilter32.c"
  226. #undef EffectFilter32
  227. #undef srcIs32BGRA
  228. #undef dstIs32BGRA
  229. // 32RGBA
  230. #define EffectFilter32 EffectFilter32RGBA
  231. #define srcIs32RGBA 1
  232. #define dstIs32RGBA 1
  233. #include "EffectFilter32.c"
  234. #undef EffectFilter32
  235. #undef srcIs32RGBA
  236. #undef dstIs32RGBA
  237. // 32ABGR
  238. #define EffectFilter32 EffectFilter32ABGR
  239. #define srcIs32ABGR 1
  240. #define dstIs32ABGR 1
  241. #include "EffectFilter32.c"
  242. #undef EffectFilter32
  243. #undef srcIs32ABGR
  244. #undef dstIs32ABGR
  245. #endif
  246.  
  247. // --------------------------------------------------------------------------------------
  248. // INTERNAL ROUTINES
  249. //    For clarity/reuse sake, the drawing code is being kept separate from the component
  250. //    interface code.
  251. // --------------------------------------------------------------------------------------
  252.  
  253.  
  254. static OSErr RequestImageFormat(
  255.                                 EffectGlobals*    glob,     // input: globals for rendering
  256.                                 EffectSourcePtr         source,     // input: source to potentially convert
  257.                                 short                    width,        // input: desired width
  258.                                 short                    height,        // input: desired height
  259.                                 OSType                    pixelFormat)// input: desired pixel format (depth & format)
  260. /*
  261.     If the data is already in the requested height and depth, returns.
  262.     Otherwise, calls decompression to get it into the format we can handle
  263. */
  264. {
  265.     OSErr                    err = noErr;
  266.     CDSequenceDataSourcePtr    sourceData = source->source.image;
  267.     ImageDescriptionHandle    curDesc = (ImageDescriptionHandle) sourceData->dataDescription;
  268.     ImageDescriptionHandle    newDesc = nil;
  269.     ImageDescriptionPtr        dp;
  270.  
  271.     dp = *curDesc;
  272.     if (
  273.         (source->effectType == kEffectRawSource) && 
  274.         ( ((dp->cType == kRawCodecType) && (dp->depth == (short)pixelFormat)) || ( dp->cType == pixelFormat) ) &&
  275.  
  276.         (dp->width == width) && 
  277.         (dp->height == height))
  278.     {
  279.         /* already got what we need */
  280.         return noErr;
  281.     }
  282.  
  283.     // otherwise, call the ICM to convert to desired data format
  284.     newDesc = (ImageDescriptionHandle) NewHandleClear(sizeof(ImageDescription));
  285.     err = MemError();
  286.  
  287.     if (err == noErr)
  288.     {
  289.         short pixelSize = QTGetPixelSize(pixelFormat);
  290.  
  291.  
  292.  
  293.         dp = *newDesc;
  294. #if ! NON_MAC_PIXEL_FORMATS
  295.  
  296.         if ((pixelFormat >> 24) != 0) {
  297.  
  298.             // non-Mac format
  299.  
  300.             dp->cType             = pixelFormat;
  301.  
  302.             dp->depth             = pixelSize;
  303.  
  304.         } else     {
  305.  
  306.             dp->cType             = kRawCodecType;
  307.  
  308.             dp->depth             = pixelFormat;
  309.  
  310.         }
  311.  
  312. #else
  313.  
  314.         dp->cType             = pixelFormat;
  315.  
  316.         dp->depth             = pixelSize;
  317.  
  318. #endif
  319.  
  320.         dp->width  = width;
  321.         dp->height = height;
  322.         dp->clutID = -1;
  323.         
  324.         /* the source is a stacked effect - or one in a format we can't handle. */
  325.         /* pass it off to the Generic Effect to convert */
  326.         /* it to a normal source */
  327.         err = ImageCodecEffectConvertEffectSourceToFormat(glob->target, source, newDesc);
  328.  
  329.         if (newDesc)
  330.         {
  331.             DisposeHandle((Handle) newDesc);
  332.         }
  333.     }
  334.  
  335.     return err;
  336.     
  337. } // RequestImageFormat
  338.  
  339. // --------------------------------------------------------------------------------------
  340. static long BlitterPreflight(BlitGlobals    *glob,     // input: globals for rendering
  341.                              short            width,     // input: width of data
  342.                              short            height, // input: height of data
  343.                              long            *depth)    // input/output: depth of data
  344. {
  345.     // *** CHANGE *** If your effect handles different bit depths, change this code to return
  346.     // what bit depths you want.
  347.     
  348.     // our blitter can handle 16 and 32 bit deep -- otherwise, we request a change to 16 bit
  349.     switch (*depth)
  350.     {
  351.         case 16:
  352.         case 32:
  353.             break;
  354.         
  355.         default:
  356.             *depth = 16;
  357.             break;
  358.     }
  359.     // *** END CHANGE ***
  360.  
  361.     // save away the actual depth we are running at
  362.     glob->width     = width;
  363.     glob->height    = height;    
  364.     glob->destDepth = *depth;
  365.     
  366.     return noErr;
  367.     
  368. } // BlitterPreflight
  369.  
  370. // --------------------------------------------------------------------------------------
  371. static long BlitterSetSource(EffectGlobals                *glob,             // input: our globals
  372.                              long                         sourceNumber,    // input: source index to set
  373.                              EffectSourcePtr            source)            // input: source value
  374. {
  375.     OSErr    err = noErr;
  376.  
  377.     if (sourceNumber >= kMaxSources)
  378.     {
  379.         // too many sources for us to handle
  380.         err = -1;
  381.     }
  382.     else
  383.     { 
  384.         // a source we can handle, save it away
  385.         err = RequestImageFormat(glob, source, glob->blitter.width, glob->blitter.height, glob->blitter.dstPixelFormat);
  386.         if (err == noErr)
  387.         {
  388.             glob->blitter.sources[sourceNumber].src = source->source.image;
  389.         }
  390.         else
  391.         {
  392.             glob->blitter.sources[sourceNumber].src = nil;
  393.         }
  394.     }
  395.         
  396.     return (err);
  397.     
  398. } // BlitterSetSource
  399.  
  400.  
  401. // --------------------------------------------------------------------------------------
  402. static long BlitterSetDest(BlitGlobals    *glob,         // input: our globals
  403.                            PixMap        *dstPixMap, // input: pixels we will draw into
  404.                            Rect            *dstRect)    // input: area of pixels we will draw into
  405. {
  406.     OSErr    result = noErr;
  407.     long    offsetH,offsetV;
  408.     char    *baseAddr;
  409.     OSType                dstPixelFormat;
  410.  
  411.  
  412.  
  413.     dstPixelFormat = GETPIXMAPPIXELFORMAT(dstPixMap);
  414.  
  415.     
  416.  
  417.     glob->dstPixelFormat = dstPixelFormat;
  418.  
  419.  
  420.  
  421.  
  422.     // *** CHANGE *** If your effect handles different bit depths, change this code
  423.     /* adjust the destination baseaddress to be at the beginning of the desired rect */
  424.     offsetH = (dstRect->left - dstPixMap->bounds.left);
  425.     if (dstPixMap->pixelSize == 16)
  426.     {
  427.         offsetH <<= 1;                    /* 1 pixel = 2 bytes */
  428.     }
  429.     else
  430.     {
  431.         if (dstPixMap->pixelSize == 32)
  432.         {
  433.             offsetH <<= 2;                    /* 1 pixel = 4 bytes */
  434.         }
  435.         else
  436.         {
  437.             result = -1;                    /* a data format we can't handle */
  438.         }
  439.     }
  440.     // *** END CHANGE ***
  441.     
  442.     offsetV = (dstRect->top - dstPixMap->bounds.top) * dstPixMap->rowBytes;
  443.     baseAddr = dstPixMap->baseAddr + offsetH + offsetV;
  444.  
  445.     glob->dstBaseAddr = baseAddr;
  446.     glob->dstRowBytes = dstPixMap->rowBytes;
  447.  
  448.     return result;
  449.     
  450. } // BlitterSetDest
  451.  
  452.  
  453. // --------------------------------------------------------------------------------------
  454. static long BlitterRenderFrame(BlitGlobals    *glob)        // input: our globals
  455. {
  456.     SInt8            mmuMode;
  457.  
  458.     // render with proper memory mode
  459.     mmuMode = true32b;
  460.     SwapMMUMode(&mmuMode);
  461.     
  462.     // convert data into base/size
  463.     {
  464.         short    i;
  465.         
  466.         for (i = 0; i < kMaxSources; ++i)
  467.         {
  468.             if (glob->sources[i].src)
  469.             {
  470.                 glob->sources[i].srcBaseAddr = glob->sources[i].src->dataPtr;
  471.                 glob->sources[i].srcRowBytes = glob->sources[i].src->dataSize / glob->height;
  472.             }
  473.         }
  474.     }
  475.         
  476.     // *** CHANGE *** If your effect handles different bit depths, write other bit depth routines and
  477.     // call them from here
  478.     
  479.     // do the actual render
  480.     switch (glob->dstPixelFormat)
  481.     {
  482.         case k32ARGBPixelFormat:
  483.             EffectFilter32ARGB(glob);
  484.             break;
  485. #if NON_MAC_PIXEL_FORMATS
  486.         case k32ABGRPixelFormat:
  487.             EffectFilter32ABGR(glob); break;
  488.         case k32BGRAPixelFormat:     // we know how to do these pixel formats
  489.             EffectFilter32BGRA(glob); break;
  490.         case k32RGBAPixelFormat:
  491.             EffectFilter32RGBA(glob); break;
  492. #endif
  493.         case k16BE555PixelFormat:
  494.             EffectFilter16BE555(glob);
  495.             break;
  496. #if NON_MAC_PIXEL_FORMATS
  497.         case k16LE565PixelFormat:
  498.             EffectFilter16LE565(glob); break;
  499.         case k16LE555PixelFormat:
  500.             EffectFilter16LE555(glob); break;
  501. #endif
  502.     }
  503.     // *** END CHANGE ***
  504.  
  505.     SwapMMUMode(&mmuMode);
  506.     
  507.     return noErr;
  508.     
  509. } // BlitterRenderFrame
  510.  
  511.  
  512. // --------------------------------------------------------------------------------------
  513. // COMPONENT ENTRY POINTS
  514. // --------------------------------------------------------------------------------------
  515.  
  516.  
  517. #define kNumPixelFormatsSupported 0x20
  518.  
  519. pascal ComponentResult EffectsFrameOpen(EffectGlobals        *glob,    // input/output: our globals
  520.                                        ComponentInstance    self)    // input: reference to ourself
  521. /*
  522.     This is called once per instance of our component.  Allocate our storage at
  523.     this point.  If we have any shared storage, we would check here to make sure
  524.     it exists, else create it.
  525. */
  526. {
  527.     ComponentResult    result;
  528.     
  529.     result = noErr;
  530.         
  531.     // first, allocate our local storage
  532.     if ((glob = (EffectGlobals*) NewPtrClear(sizeof(EffectGlobals)))==nil)
  533.     {
  534.         result = MemError();
  535.         goto bail;
  536.     }
  537.     
  538.     SetComponentInstanceStorage(self, (Handle) glob);
  539.     
  540.     // we are ourselves, and the current top of chain is us
  541.     glob->self = self;
  542.     glob->target = self;
  543.     glob->wantedDestinationPixelTypeH = (OSType **) NewHandleClear(sizeof(OSType) * (kNumPixelFormatsSupported + 1));
  544.     
  545.     // open the generic effect, this will handle effects we can't handle ourselves
  546.     result = OpenADefaultComponent(decompressorComponentType, kEffectGenericType, &glob->delegate);
  547.     if (result)
  548.         goto bail;
  549.         
  550.     // set up the target for the components below us
  551.     EffectsFrameTarget(glob, self);
  552.  
  553. bail:
  554.     return(result);
  555.     
  556. } // EffectsFrameOpen
  557.  
  558.  
  559. // --------------------------------------------------------------------------------------
  560. // Called each time an instance of our component is going away.  Toss anything we allocated.
  561. pascal ComponentResult EffectsFrameClose(EffectGlobals        *glob,    // input: our globals
  562.                                         ComponentInstance    self)    // input: reference to ourself
  563. {
  564. #pragma unused (self)
  565.  
  566.     if (glob)
  567.     {
  568.         /*     *** CHANGE *** DISPOSE OF YOUR TWEENERS */
  569.         DisposeTweenRecord(&glob->percentage);
  570.  
  571.         /* *** END CHANGE *** */
  572.  
  573.  
  574.  
  575.         DisposeTweenGlobals(&glob->tweenGlobals);
  576.  
  577.         CloseComponent(glob->delegate);
  578.  
  579.  
  580.         DisposeHandle((Handle) glob->wantedDestinationPixelTypeH);
  581.  
  582.  
  583.         DisposePtr((Ptr) glob);
  584.     }
  585.     return(noErr);
  586.     
  587. } // EffectsFrameClose
  588.  
  589.  
  590. // --------------------------------------------------------------------------------------
  591.  
  592. pascal ComponentResult EffectsFrameTarget(EffectGlobals        *glob,    // input: our globals
  593.                                           ComponentInstance target)    // input: reference to new top of chain
  594. /*
  595.     Called when there is a new top of the calling chain.  Remember that ourselves, and tell
  596.     those below us as well.
  597. */
  598. {
  599.     // remember who is top of chain
  600.     glob->target = target;
  601.     
  602.     // and tell folks below us, too.
  603.     ComponentSetTarget(glob->delegate, target);
  604.     
  605.     return(noErr);
  606.     
  607. } // EffectsFrameTarget
  608.  
  609.  
  610. // --------------------------------------------------------------------------------------
  611.  
  612. pascal ComponentResult EffectsFrameVersion(EffectGlobals    *glob)        // input: our globals
  613. /*
  614.     Called to obtain the version of our component.
  615. */
  616. {
  617. #pragma unused (glob)
  618.     
  619.     return kDimmerEffectVersion;
  620.     
  621. } // EffectsFrameVersion
  622.  
  623.  
  624. // --------------------------------------------------------------------------------------
  625. //    Called to prepare for a sequence of frames.  
  626. //    Return in p->capabilities anything in particular your effect requires, such as 
  627. //    limitations on bitdepth.
  628. pascal long EffectsFrameEffectSetup(EffectGlobals            *glob,     // input: our globals
  629.                                      CodecDecompressParams    *p)        // input: information about the thing being decompressed
  630.  
  631. {
  632.     CodecCapabilities     *capabilities = p->capabilities;
  633.     OSErr                err;
  634.     OSType                 *formats = *glob->wantedDestinationPixelTypeH;
  635.     long                wantedPixelSize = capabilities->wantedPixelSize;
  636.     OSType                dstPixelFormat;
  637.     
  638.     dstPixelFormat = GETPIXMAPPIXELFORMAT(&p->dstPixMap);
  639.  
  640.     
  641.  
  642.     switch (dstPixelFormat)
  643.     {
  644.         case k32ARGBPixelFormat:
  645.         case k16BE555PixelFormat:
  646. #if NON_MAC_PIXEL_FORMATS
  647.         case k32BGRAPixelFormat:     // we know how to do these pixel formats
  648.         case k32ABGRPixelFormat:
  649.         case k32RGBAPixelFormat:
  650.         case k16LE565PixelFormat:
  651.         case k16LE555PixelFormat:
  652. #endif
  653.             *formats++ = dstPixelFormat;
  654.             break;
  655.         default:                    // we prefer 16 over 32
  656. #if NON_MAC_PIXEL_FORMATS
  657.             *formats++ = k16LE555PixelFormat;
  658.             *formats++ = k16LE565PixelFormat;
  659.             *formats++ = k32BGRAPixelFormat;
  660.             *formats++ = k32RGBAPixelFormat;
  661.             *formats++ = k32ABGRPixelFormat;
  662. #endif
  663.             *formats++ = k16BE555PixelFormat;
  664.             *formats++ = k32ARGBPixelFormat;
  665.             break;
  666.     }
  667.  
  668.  
  669.  
  670.     // NOTE: 0 marks the end of the format list
  671.  
  672.     *formats++ = 0;
  673.  
  674.  
  675.     /* set up our blitter */
  676.     err = BlitterPreflight(&glob->blitter,
  677.                            (*p->imageDescription)->width,
  678.                            (*p->imageDescription)->height,
  679.                            &wantedPixelSize);
  680.     
  681.     capabilities->wantedPixelSize = 0;
  682.  
  683.     p->wantedDestinationPixelTypes = glob->wantedDestinationPixelTypeH;
  684.  
  685.  
  686.     return (err);
  687.     
  688. } // EffectsFrameEffectSetup
  689.  
  690. // --------------------------------------------------------------------------------------
  691.  
  692. //    Called for each frame, before the request to actually draw
  693. pascal long EffectsFrameEffectBegin(EffectGlobals            *glob,    // input: our globals
  694.                              CodecDecompressParams    *p,     // input: info about frame being drawn
  695.                              EffectsFrameParamsPtr    effect)    // input: info about this effect frame
  696. {
  697.     OSErr                    err = noErr;
  698.     EffectSourcePtr            source;
  699.     long                    numSources = 0;
  700.     wide                    percentage;
  701.  
  702.     #if kMaxAsyncFrames > 0
  703.         /* we can go async if we don't already have an effect scheduled */
  704.         if (glob->asyncCount < kMaxAsyncFrames)
  705.         {
  706.             glob->asyncCount++;
  707.             effect->doAsync = true;
  708.         }
  709.     #endif
  710.  
  711.     // dest changed? 
  712.     if (p->conditionFlags & 
  713.             (codecConditionNewClut+codecConditionFirstFrame+codecConditionNewDepth+codecConditionNewDestination+codecConditionNewTransform))
  714.     {
  715.         // re-scan the sources
  716.         glob->majorSourceChangeSeed = 0;
  717.  
  718.         // re-read the parameters
  719.         glob->frameNumber = 0;
  720.  
  721.         err = BlitterSetDest(&glob->blitter, &p->dstPixMap, &p->dstRect);
  722.         if (err != noErr)
  723.             goto bail;
  724.  
  725.     }
  726.  
  727.     // new sources?  make note of them!
  728.     if (p->majorSourceChangeSeed != glob->majorSourceChangeSeed)
  729.     {
  730.         // grab start of input chain for this effect
  731.         source = effect->source;
  732.  
  733.         /* we can play with up to kMaxSources sources, so go get them */
  734.         while (source != nil && numSources < kMaxSources)
  735.         {        
  736.             /* now give that source to our blitter */
  737.             err = BlitterSetSource(glob, numSources, source);
  738.             if (err != noErr)
  739.                 goto bail;
  740.                 
  741.             source = source->next;
  742.             ++numSources;
  743.         }
  744.  
  745.  
  746.  
  747.         glob->majorSourceChangeSeed = p->majorSourceChangeSeed;
  748.     }
  749.     
  750.     /* if this is a new frame, or the same frame with a new length, get rid of our old parameters & tweeners */    
  751.     if ((effect->frameTime.frameNumber != glob->frameNumber) || (effect->frameTime.virtualDuration != glob->virtualDuration) )
  752.     {
  753.         /*     *** CHANGE *** DISPOSE OF YOUR TWEENERS */
  754.         DisposeTweenRecord(&glob->percentage);
  755.         
  756.         /* *** END CHANGE *** */
  757.  
  758.  
  759.  
  760.         DisposeTweenGlobals(&glob->tweenGlobals);
  761.  
  762.         glob->initialized = false;
  763.         glob->frameNumber = effect->frameTime.frameNumber;
  764.         glob->virtualDuration = effect->frameTime.virtualDuration;
  765.     }
  766.  
  767.     // Read in effect parameters
  768.     if (!glob->initialized)
  769.     {
  770.         Ptr                     data = p->data;
  771.         OSErr                    err;
  772.         long                    index = 1;
  773.         
  774.         err = InitializeTweenGlobals(&glob->tweenGlobals, p);
  775.         if (err!=noErr)
  776.             goto bail;
  777.             
  778.         /*     *** CHANGE *** TIME TO READ IN PARAMETERS TO YOUR EFFECT:
  779.             You can read any number of atoms you wish from the container.  For example, you might have a 
  780.             'star' (start) and 'end ' (end) value.  They might be expressed as percentages, numbers, or other values.
  781.             Or, you might have multiple atoms of type 'para' (param) which would be read in by calling
  782.             QTFindChildByIndex with various index values.  If you want to know how many parameters of a given
  783.             type there are, call QTCountChildrenOfType.  These parameters are specific to your particular effect,
  784.             and will need to be placed there by whoever is authoring the title.
  785.             
  786.             If you require parameters, and they aren't there, return an error.  If you can default the values
  787.             if they are missing, do so and continue.  In general, I'd recommend having a default case unless
  788.             you really are unable to implement it for a technical reason.
  789.             
  790.             These parameters are those that apply to the effect itself.  Later, we'll translate some of these parameters
  791.             into how they relate to *where* in the effect we are.  For example, an effect that runs from a starting
  792.             percentage of 10 to an ending percentage of 90 will have 10 and 90 as parameters here.
  793.         */
  794.         
  795.         /* make our tweener, return if we already have it */
  796.         err = CreateTweenRecord(&glob->tweenGlobals, &glob->percentage, 
  797.                         kParameterUsagePercent, 1, 
  798.                         sizeof(Fixed), kTweenTypeFixed, (void*)0, (void*)fixed1,  
  799.                         effect->frameTime.virtualDuration);
  800.         if (err!=noErr)
  801.             goto bail;
  802.                         
  803.  
  804.  
  805.         /* *** END CHANGE *** */
  806.  
  807.  
  808.  
  809.         glob->initialized = true;
  810.     }
  811.     
  812.     /* determine the amount we are along the tween via the current time - start time */
  813.     percentage = effect->frameTime.value;
  814.     CompSub(&effect->frameTime.virtualStartTime, &percentage);
  815.         
  816.     
  817.     /*     Tween our parameters and get the current value for this frame, prepare to render
  818.         it when the RenderFrame happens. */
  819.     if (err == noErr)
  820.         {
  821.         Fixed    thePercentage;
  822.         
  823.         /* ***** CHANGE TO TWEEN YOUR EFFECTS PARAMETERS */
  824.         
  825.         if (glob->percentage.tween)
  826.             QTDoTween(glob->percentage.tween, percentage.lo, glob->percentage.tweenData, nil, nil, nil );
  827.         
  828.         thePercentage = **(Fixed**)(glob->percentage.tweenData);
  829.         // If we are before the half-way point of this transition, we should
  830.         // be fading the first source to black
  831.         if (thePercentage < fixed1/2)
  832.         {
  833.             (glob->blitter).direction = 1;
  834.             (glob->blitter).dimValue = FixedToInt(FixMul(IntToFixed(512), thePercentage));
  835.         }
  836.         // Otherwise, we are fading up onto the new source
  837.         else
  838.         {
  839.             (glob->blitter).direction = 0;
  840.             (glob->blitter).dimValue = FixedToInt(FixMul(IntToFixed(512), thePercentage)) - 255;
  841.         }
  842.  
  843.         /* ***** END CHANGE */
  844.         }
  845.  
  846.     if (glob->tweenGlobals.atLeastOneTweener)
  847.         {
  848.         // this effect runs constantly
  849.         p->needUpdateOnTimeChange = true;
  850.         p->needUpdateOnSourceChange = false;
  851.         }
  852.     else
  853.         {
  854.         // this effect only needs to run when the sources actually change
  855.         p->needUpdateOnTimeChange = false;
  856.         p->needUpdateOnSourceChange = true;
  857.         }
  858.     
  859.         
  860. // EXCEPTION HANDLING
  861. bail:
  862.     #if kMaxAsyncFrames > 0
  863.         // if we didn't queue the frame, then remove it from used list
  864.         if (err != noErr)
  865.             glob->asyncCount--;
  866.     #endif
  867.     
  868.     return err;
  869.     
  870. } // EffectsFrameEffectBegin
  871.  
  872.  
  873. // --------------------------------------------------------------------------------------
  874. pascal long EffectsFrameEffectRenderFrame(EffectGlobals             *glob,         // input: our globals
  875.                                     EffectsFrameParamsPtr    effect)        // input: effect frame to be rendered
  876. /*
  877.     Start rendering of the given frame.
  878. */
  879. {
  880. #pragma unused (effect)
  881.  
  882.     /* render the frame */
  883.     BlitterRenderFrame(&glob->blitter);
  884.     
  885.     #if kMaxAsyncFrames > 0
  886.         glob->asyncCount--;
  887.     #endif
  888.  
  889.     return noErr;
  890.     
  891. } // EffectsFrameEffectRenderFrame
  892.  
  893.  
  894. // --------------------------------------------------------------------------------------
  895. pascal long EffectsFrameEffectCancel(EffectGlobals            *glob,         // input: our globals
  896.                                     EffectsFrameParamsPtr    effect)        // input: effect frame to be canceled
  897. /*
  898.     Halt rendering of the given frame, even if it is only partially completed.
  899. */
  900. {
  901. #pragma unused (effect)
  902. #pragma unused (glob)
  903.  
  904.     #if kMaxAsyncFrames > 0
  905.         glob->asyncCount--;
  906.     #endif
  907.  
  908.     return noErr;
  909.     
  910. } // EffectsFrameEffectCancel
  911.  
  912.  
  913. // ----------------------------------------------------------------------------------------
  914.  
  915. pascal ComponentResult EffectsFrameGetCodecInfo(EffectGlobals    *glob,
  916.                                                 CodecInfo        *info)
  917. /*
  918.  *    CDGetCodecInfo allows us to return information about ourselves to the codec manager.
  919.  *    
  920.  *    There will be a tool for determining appropriate values for the accuracy, speed
  921.  *    and level information. For now we estimate with scientific wild guessing.
  922.  *
  923.  *  The info is stored as a resource in the same file with our component.
  924.  */
  925. {
  926.     OSErr err = noErr;
  927.  
  928.     if (info == nil)
  929.     {
  930.         err = paramErr;
  931.     }
  932.     else
  933.     {
  934.         CodecInfo **tempCodecInfo;
  935.  
  936.         err = GetComponentResource((Component) glob->self,
  937.                                    codecInfoResourceType,
  938.                                    kEffectcdciRes,
  939.                                    (Handle *) &tempCodecInfo);
  940.         if (err == noErr)
  941.         {
  942.             *info = **tempCodecInfo;
  943.             DisposeHandle((Handle) tempCodecInfo);
  944.         }
  945.     }
  946.  
  947.     return err;
  948.     
  949. } // EffectsFrameGetCodecInfo
  950.  
  951.  
  952. // ---------------------------------------------------------------------------------------------------------------------------
  953. pascal ComponentResult EffectsFrameGetParameterListHandle(EffectGlobals    *glob,        // input: our globals
  954.                                                          Handle            *theHandle)    // output: the parameter description for this effect
  955. {
  956.     OSErr                    err = noErr;
  957.     
  958.     err = GetComponentResource((Component) glob->self,
  959.                                FOUR_CHAR_CODE('atms'),
  960.                                kEffectatmsRes,
  961.                                theHandle);
  962.     
  963.     return(err);
  964.     
  965. } // EffectsFrameGetParameterListHandle
  966.  
  967. // ----------------------------------------------------------------------------------------
  968. pascal long EffectsFrameEffectGetSpeed(EffectGlobals * glob, QTAtomContainer parameters, Fixed *pFPS)
  969. {
  970. #pragma unused (glob, parameters)
  971.  
  972.     if (pFPS)
  973.         *pFPS = IntToFixed(30);
  974.         
  975.     return noErr;
  976.     
  977. } // EffectsFrameEffectGetSpeed
  978.  
  979.  
  980.